package com.itheima.proxy.Jdk;

import com.sun.org.apache.xpath.internal.SourceTree;
import org.springframework.cglib.core.DebuggingClassWriter;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author by itheima
 * @Date 2021/11/21
 * @Description
 */
public class JdkDemo {
    /**
     * jdk代理中：目标对象与代理对象关系：
     *  兄弟关系
     *      它们都实现共同的接口
     * @param args
     */
    public static void main(String[] args) {
        //输出动态生成的代理对象字节码文件
        System.setProperty("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");
        //目标对象
        Car tesla = new Tesla();
        //生成代理对象
        /*
            参数1：指定类加载器
            参数2：指定接口的字节码组成的数组
            参数3：方法增强具体实现
         */
        Car teslaProxy = (Car) Proxy.newProxyInstance(
                tesla.getClass().getClassLoader(),
                tesla.getClass().getInterfaces(),
                new InvocationHandler() {
                    /**
                     *
                     * @param proxy 生成的代理对象引用
                     * @param method 当前被被拦截的方法对象
                     * @param args 方法的入参
                     * @return
                     * @throws Throwable
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //无限递归---》栈内存溢出 开发慎用
                        //Object result = method.invoke(proxy, args);
                        //打印开始时间 前置通知
                        long startTime = System.currentTimeMillis();
                        System.out.println("开始时间："+startTime);
                        //原始方法执行
                        //如果无返回值void，那么result=null
                        Object result = null;
                        try {
                            result = method.invoke(tesla, args);
                            //后置通知
                            long endTime = System.currentTimeMillis();
                            System.out.println("结束时间："+endTime);
                        } catch (Exception e) {
                            //异常通知
                            System.out.println(e.getMessage());
                        }  finally {
                            //最终通知 无论是否发生异常，都会被执行
                            System.out.println("最终通知。。。。");
                        }

                        return result;
                    }
                });
        teslaProxy.run();
    }

}
